﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Dynamic;
using System.Collections;

namespace Ruandao.Misc
{
    public class DynamicXmlNodeList : DynamicObject, IEnumerable
    {
        private List<XElement> _elements;

        internal DynamicXmlNodeList(IEnumerable<XElement> elements)
        {
            _elements = new List<XElement>(elements);
        }

        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            Type targetType = binder.ReturnType;

            if (targetType == typeof(IEnumerable))
            {
                result = this;
                return true;
            }

            return base.TryConvert(binder, out result);
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            if (string.CompareOrdinal(binder.Name, "Item") == 0)
            {
                if (args.Length == 1)
                {
                    XElement element = _elements[Convert.ToInt32(args[0])];
                    result = new DynamicXmlNode(element);
                    return true;
                }
            }

            return base.TryInvokeMember(binder, args, out result);
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (string.CompareOrdinal(binder.Name, "Length") == 0)
            {
                result = _elements.Count;
                return true;
            }

            return base.TryGetMember(binder, out result);
        }

        #region Implementation of IEnumerable
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new NodeEnumerator(_elements.GetEnumerator());
        }
        #endregion

        private sealed class NodeEnumerator : IEnumerator
        {

            private IEnumerator<XElement> _elementEnumerator;

            public NodeEnumerator(IEnumerator<XElement> elementEnumerator)
            {
                _elementEnumerator = elementEnumerator;
            }

            public object Current
            {
                get
                {
                    XElement element = _elementEnumerator.Current;
                    return new DynamicXmlNode(element);
                }
            }

            public bool MoveNext()
            {
                return _elementEnumerator.MoveNext();
            }

            public void Reset()
            {
                _elementEnumerator.Reset();
            }
        }
    }
}
